package eafit.sicom.mpark;

import android.app.Activity;
import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;

public class GpsManager /* implements LocationListener */{

	
	private final int TIME = 10000; // miliseconds
	private final int UPDATE_DISTANCE = 10; // meters

	/**
	 * Latitude that corresponds to the Eafit university
	 */
	public static double LATITUDE_REFERENCE = 6.200352181135478;

	/**
	 * Longitude that corresponds to the Eafit university
	 */
	public static double LONGITUDE_REFERENCE = -75.57862043380737;

	public enum PROXIMITY {
		HIGH_HIGH, HIGH, MEDIUM, LOW, LOW_LOW
	};

	private Location location;

	private double latitude;
	private double longitude;
	private Activity activity;
	private LocationManager locationManager;

	public GpsManager(Activity act) {
		this.activity = act;

		longitude = 0;
		latitude = 0;

		//Log.d("*****************", "P** GPSTart");
	}

	public void registerLocationListener() {
		String context = Context.LOCATION_SERVICE;
		locationManager = (LocationManager) activity.getSystemService(context);
		String provider = getCriteria(locationManager);

//		Log.d("*****************", "P** GPSregisterlocationlistener");

		location = locationManager.getLastKnownLocation(provider);
		UpdateLocation(location);

		locationManager.requestLocationUpdates(provider, TIME, UPDATE_DISTANCE,
				locationListener);
	}

	private void UpdateLocation(Location location) {

//		Log.d("*****************", "P** GPSupdateLocation");

		if (location != null) {
			//MParkActivity.timeScheduleUpdateParking = calcUpdateTime();
			latitude = location.getLatitude();
			longitude = location.getLongitude();
		} 
	}
	
	private int calcUpdateTime() {
		PROXIMITY proximity = PROXIMITY.LOW_LOW;

		if (proximity == PROXIMITY.HIGH_HIGH) {
			return 3000;
		} else if (proximity == PROXIMITY.HIGH) {
			return 7000;
		} else if (proximity == PROXIMITY.MEDIUM) {
			return 10000;
		} else if (proximity == PROXIMITY.LOW) {
			return 15000;
		} else if (proximity == PROXIMITY.LOW_LOW) {
			return 20000;
		} else {//Will never happen
			return 20000;
		}
	}

	private String getCriteria(LocationManager locationManager) {
		Criteria criteria = new Criteria();
		criteria.setAccuracy(Criteria.ACCURACY_FINE);
		criteria.setAltitudeRequired(false);
		criteria.setBearingRequired(false);
		criteria.setCostAllowed(true);
		criteria.setPowerRequirement(Criteria.POWER_LOW);
		return locationManager.getBestProvider(criteria, true);
	}

	private final LocationListener locationListener = new LocationListener() {
		public void onLocationChanged(Location location) {

			UpdateLocation(location);
	
		}

		public void onProviderDisabled(String provider) {
			UpdateLocation(null);

		}

		public void onProviderEnabled(String provider) {

		}

		public void onStatusChanged(String provider, int status, Bundle extras) {
		}
	};

	public double getLatitude() {
		return latitude;
	}

	public double getLongitude() {
		return longitude;
	}
	
public void removeUpdates() {
	locationManager.removeUpdates(locationListener);
}

	/**
	 * Compare the current position with the LATITUDE_REFERENCE and
	 * LONGITUDE_REFERENCE to check proximity
	 * 
	 * @return
	 */
	public PROXIMITY getCurrentProximity() {

		double difLatitude = Math.abs(this.latitude
				- GpsManager.LATITUDE_REFERENCE);
		double difLongitude = Math.abs(this.longitude
				- GpsManager.LONGITUDE_REFERENCE);

		// Distance between two points
		double distance = Math.sqrt(difLatitude * difLatitude + difLongitude
				* difLongitude);

		distance = castDegreeToMeters(distance);

		// Log.d("P**", "P** Ditance from Eafit: " + distance + " meters");

		if (distance <= 8000 && distance >= 5500) {
			return PROXIMITY.LOW_LOW;
		} else if (distance < 5500 && distance >= 4500) {
			return PROXIMITY.LOW;
		} else if (distance <= 4500 && distance >= 3500) {
			return PROXIMITY.MEDIUM;
		} else if (distance <= 3500 && distance >= 1500) {
			return PROXIMITY.HIGH;
		} else if (distance < 1500 && distance >= 0) {
			return PROXIMITY.HIGH_HIGH;
		} else {
			return PROXIMITY.LOW_LOW;
		}

	}

	private double castDegreeToMeters(double degrees) {
		// One degree of latitude equals 60 nautical miles. A nautical mile is
		// 1852 meters.
		return 111120 * degrees;

	}
}
